%% chapter 3 exercise in Erlang programming
%% author: gaoyunpeng
-module(chapter3).
-export([sum/1,sum/2]).
-export([create/1,reverse_create/1]).
-export([print/1]).
%%-export([new/0,destory/1,write/3,delete/2,read/2,match/2]).
%%-export([filter/2,reverse/1,concatenate/1,flatten/1]).
-export([qsort/1,msort/1]).
%% exercise 3-1

sum(N) when N > 1 -> N + sum(N-1);
sum(1) -> 1;
sum(_) -> {error}.

sum(N,M) when N =< M -> N + sum(N+1,M);
sum(N,M) when N == M -> N;
sum(_,_) -> {error}.

%% exercise 3-2

create(N) when N > 1-> create(N-1)++[N];
create(1) -> [1];
create(_) -> {error}.

reverse_create(N) when N > 1 -> [N | reverse_create(N-1)];
reverse_create(1) -> [1];
reverse_create(_) -> {error}.

%% exercise 3-3
print(N) when N > 2 , N rem 2 == 0 -> 
	print(N - 2),
	io:format("Number:~p~n",[N]);
print(2) -> io:format("Number:~p~n",[2]);
print(N) when N > 2 , N rem 2 /= 0 -> print(N-1);
print(_) -> {invalid}.

%% exercise 3-4

%%new() -> [].
%%destory(_Db) -> {ok}.
%%write(Key,Element,Db) ->
%%	lists:append({Key,Element},Db).
%%read(Key,[ Head | Tail ]) when Tail /= [] ->

%% exercise 3-5

%%filter(List,Num)


%% exercise 3-6
filter_less(List,Num) when List /= [] ->
	[H|T] = List,
	if 
		H < Num -> [H | filter_less(T,Num)];
		H >= Num -> filter_less(T,Num)
	end;
filter_less(_List,_Num) ->
	[].
filter_greater(List,Num) when List /= [] ->
	[H|T]= List,
	if 
		H >= Num -> [H | filter_greater(T,Num)];
		H < Num 	-> filter_greater(T,Num)
	end;
filter_greater(_List,_Num)  ->
	[].
qsort(List) when List /= [] ->
	[ Head | Tail ] = List,
	First =  filter_less(Tail,Head),
	Second = filter_greater(Tail,Head),
	qsort(First)++[Head]++qsort(Second);

qsort(_List)  ->
	[].

merge(_List1,_List2) when _List1 == [] , _List2 == []->
	[];
merge(_List1,List2) when _List1 == [] ->
	List2;
merge(List1,_List2) when _List2 == [] ->
	List1;
merge(List1,List2) ->
	[F1 | S1] = List1,
	[F2 | S2] = List2,
	if
		F1 > F2  -> [F2 | merge(List1,S2)];
		F1 =< F2 -> [F1 | merge(List2,S1)]
	end.
msort(List)  when length(List) > 1 ->
	N = length(List) div 2,
	{First,Second} = lists:split(N,List),
	Sfirst = msort(First),
	Ssecond = msort(Second),
	merge(Sfirst,Ssecond);
msort(List) when length(List) == 1 ->
	List;
msort(_List) ->
	[].





















